package service

import (
	"admin-system-go/model"
	"admin-system-go/model/do"
	"admin-system-go/model/dto"
	"admin-system-go/repository"
	"admin-system-go/repository/user_dao"
	"admin-system-go/util"
	"github.com/google/uuid"
	"strconv"
	"time"
)

type (
	UserService interface {
		Login(loginDTO dto.LoginDTO) model.ResponseEntity
		RegisterUser(userDto dto.UserAddDTO) model.ResponseEntity
		ChangeUserPassword(changPasswordDTO dto.ChangPasswordDTO) model.ResponseEntity
		UpdateUser(userDto dto.UserUpdateDTO) model.ResponseEntity
		DeleteUser(userDto dto.UserDelDTO) model.ResponseEntity
		QueryUser(userDto dto.UserQueryDTO) model.ResponseEntity
		GetUserById(uid uint) model.ResponseEntity
		AddUserToGroup(dto.UserAddGroupDTO) model.ResponseEntity
		CreateToken(uid uint, expired time.Time) do.Token
		QueryToken(token do.Token) []do.Token
		ValidToken(token do.Token) bool
		RemoveToken(uid uint)
	}
)

type userServiceImpl struct {
}

func (userService userServiceImpl) Login(loginDTO dto.LoginDTO) model.ResponseEntity {
	user := do.User{}
	result := repository.GetDb().Where(&loginDTO).Find(&user)
	if result.RowsAffected == 1 {
		return model.SuccessEntityModel(user.Uid)
	} else {
		return model.FailEntityModel("用户名或密码错误")
	}
}

func (userService userServiceImpl) RegisterUser(userDto dto.UserAddDTO) model.ResponseEntity {
	if user_dao.GetUserByUsername(userDto.Username) != nil {
		return model.FailEntityModel("用户名已经存在")
	}
	if userDto.Password == "" {
		userDto.Password = "123456"
		userDto.State = 0
	}
	var user do.User
	_ = repository.Copy(userDto, &user)
	uid := util.GenID()
	user.Uid = uid
	err := user_dao.InsertUser(&user)
	if err != nil {
		return model.FailEntityModel(err.Error())
	}
	return model.SuccessEntityModel(true)
}
func (userService userServiceImpl) ChangeUserPassword(changPasswordDTO dto.ChangPasswordDTO) model.ResponseEntity {
	odlUser := user_dao.GetUserById(changPasswordDTO.Uid)
	if odlUser == nil {
		return model.FailEntityModel("用户不存在")
	}
	if odlUser.Password != changPasswordDTO.OldPassword {
		return model.FailEntityModel("原密码输入错误")
	}
	odlUser.Password = changPasswordDTO.Password
	result := user_dao.UpdateUser(odlUser)
	return model.SuccessEntityModel(result)
}
func (userService userServiceImpl) UpdateUser(userDto dto.UserUpdateDTO) model.ResponseEntity {

	odlUser := user_dao.GetUserById(userDto.Uid)
	if odlUser == nil {
		return model.FailEntityModel("用户不存在")
	}
	_ = repository.Copy(userDto, odlUser)
	result := user_dao.UpdateUser(odlUser)
	return model.SuccessEntityModel(result)
}
func (userService userServiceImpl) DeleteUser(userDto dto.UserDelDTO) model.ResponseEntity {
	tx := repository.GetDb().Begin()
	tx.Where("uid IN ?", userDto.Ids).Delete(&do.User{})
	tx.Where("uid IN ?", userDto.Ids).Delete(&do.GroupUser{})
	tx.Commit()
	return model.SuccessEntityModel(tx.RowsAffected > 0)

}
func (userService userServiceImpl) QueryUser(userDto dto.UserQueryDTO) model.ResponseEntity {
	var user do.User
	_ = repository.Copy(userDto, &user)
	user.Uid = 0
	pageSize := userDto.PageSize
	pageNo := userDto.PageNo
	var users []do.User
	_ = repository.GetDb().Where(&user).Where("uid != ?", userDto.Uid).Limit(pageSize).Offset((pageNo - 1) * pageSize).Find(&users)
	var result = make([]dto.UserQueryDTO, len(users))
	var total int64
	if len(users) != 0 {
		_ = repository.GetDb().Model(&do.User{}).Where(&user).Where("uid != ?", userDto.Uid).Count(&total)
	}
	_ = repository.CopySlice(users, result)
	return model.PageEntityModel(result, &model.PageInfo{
		Total:    total,
		PageSize: pageSize,
		PageNo:   pageNo,
	})
}

func (userService userServiceImpl) GetUserById(uid uint) model.ResponseEntity {
	var user do.User
	_ = repository.GetDb().Model(&user).Where("uid = ?", uid).Find(&user)
	var result dto.UserBaseDTO
	_ = repository.Copy(user, &result)
	return model.SuccessEntityModel(result)
}

func (userService userServiceImpl) AddUserToGroup(useAddGroupDto dto.UserAddGroupDTO) model.ResponseEntity {
	var userGroupLink []do.GroupUser = make([]do.GroupUser, 0)
	for _, userGroupId := range useAddGroupDto.UserGroupIds {
		for _, uidStr := range useAddGroupDto.Uids {
			uid, _ := strconv.Atoi(uidStr)
			userGroupLink = append(userGroupLink, do.GroupUser{Uid: uint(uid), GroupId: uint(userGroupId)})
		}
	}
	tx := repository.GetDb().Create(userGroupLink)
	if tx.Error != nil {
		return model.FailEntityModel(tx.Error.Error())
	}
	return model.SuccessEntityModel(tx.RowsAffected)
}

func (userService userServiceImpl) CreateToken(uid uint, expired time.Time) do.Token {
	if expired.IsZero() {
		expired = time.Now().Add(time.Minute * 5)
	}
	random, _ := uuid.NewRandom()

	token := do.Token{
		Uid:     uid,
		Token:   random.String(),
		Expired: expired,
	}
	_ = repository.GetDb().Create(&token)
	return token
}
func (userService userServiceImpl) ValidToken(token do.Token) bool {
	_ = repository.GetDb().Find(&token)
	if token.Expired.After(time.Now()) {
		return false
	} else {
		return true
	}
}
func (userService userServiceImpl) RemoveToken(uid uint) {
	repository.GetDb().Where("uid", uid).Delete(&do.Token{})
}

func (userService userServiceImpl) QueryToken(token do.Token) []do.Token {
	tokens := make([]do.Token, 0)
	repository.GetDb().Model(&do.Token{}).Where(&token).Find(tokens)
	return tokens
}
